﻿using System;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace UFrame
{
    /*
     5. 设计一个生成Data保存类的程序(小游戏设计)
    字段:
    实物字段(金币 等级 所在关卡):默认值
    虚拟字段(道具是否存在过)

    设计生成器:
    int levelNum entity 1 call
    string levelKeyDisappear virtual 1

    call 代表回调 
    用于生成laya的代码
    */
    public class LayaCreateEditor
    {
        public static string path = "/BawAsset/PlayerPrefs/";

        [MenuItem("Plateface/ORM/LayaCode")]
        public static void LayaCode()
        {
            var comPath = Application.dataPath + path;

            DirectoryInfo d = new DirectoryInfo(comPath);
            var files = d.GetFiles();

            var templateClass = DefineLayaScript.templateClass;
            foreach (var item in files)
            {
                string className = Path.GetFileNameWithoutExtension(item.Name);

                string s = File.ReadAllText(item.FullName,Encoding.UTF8);
                var allLine = s.Split(new string[] { "\r\n" }, StringSplitOptions.None);

                var classInfoSB = GenerateClass(allLine);

                templateClass = templateClass.Replace("${className}", className);
                templateClass = templateClass.Replace("${classContent}", classInfoSB.GetClassContent());
                templateClass = templateClass.Replace("${classLoad}",
                    DefineLayaScript.loadMethod.Replace("${classLoad}", classInfoSB.initMethod.ToString()));

                templateClass = templateClass.Replace("${classSave}",
                    DefineLayaScript.saveMethod.Replace("${classSave}", classInfoSB.saveMethod.ToString()));

                Debug.Log(templateClass);
            }
        }

        private static LayaRefSB GenerateClass(string[] allLine)
        {
            LayaRefSB p = new LayaRefSB();
            foreach (var line in allLine)
            {
                if (string.IsNullOrEmpty(line))
                {
                    continue;
                }

                string[] charAry = StringTool.SplitSpacing(line);
                string fieldType = charAry[0];
                string fieldName = charAry[1];
                bool isEntity = charAry[2].Equals("entity", StringComparison.OrdinalIgnoreCase);
                string defaultVal = charAry[3];

                string unName = fieldName + "Un";
                p.fieldUn.AppendLine(string.Format("private string {0} = \"{1}\";", unName, unName));
                p.fieldUn.AppendLine();

                string maxFieldType = fieldType.Substring(0, 1).ToUpper() + fieldType.Substring(1);
                string maxFieldName = fieldName.Substring(0, 1).ToUpper() + fieldName.Substring(1);

                if (isEntity)
                {
                    p.fieldCall.AppendLine(string.Format("public Action<{0}> On{1};", fieldType, fieldName));
                    p.field.AppendLine(string.Format("private {0} {1} = {2};", fieldType, fieldName, defaultVal));

                    p.property.AppendLine(string.Format("public {0} {1} \n" +
                                                        "{{\n" +
                                                        "get {{ return {2}; }}\n" +
                                                        "set{{\n" +
                                                        "if({2} == value)\n" +
                                                        "return;\n" +
                                                        "{2} = value;\n" +
                                                        "PlayerPrefs.Set{4}({3}, {2});\n" +
                                                        "if(On{2} != null)\n" +
                                                        "On{2}({2});\n" +
                                                        "}}\n" +
                                                        "}}\n", fieldType, maxFieldName, fieldName, unName,
                        maxFieldType));

                    p.initMethod.AppendLine(string.Format("{0} = PlayerPrefs.Get{3}({1}, {2});\n", fieldName, unName,
                        defaultVal, maxFieldType));

                    p.saveMethod.AppendLine(string.Format("PlayerPrefs.Set{2}({0}, {1});", unName, fieldName,
                        maxFieldType));
                }
                else
                {
                    string setMethod = "public void Set{0}(string s)"
                                       + "{{\n"
                                       + "PlayerPrefs.SetString({1}, \"{2}\");\n"
                                       + "}}\n";

                    string getMethod = "public {0} Get{1}(string s)"
                                       + "{{\n"
                                       + "return PlayerPrefs.GetString({2}, \"{3}\");\n"
                                       + "}}\n";

                    p.virtualMethod.AppendLine(string.Format(setMethod, maxFieldName, unName, defaultVal));

                    p.virtualMethod.AppendLine(string.Format(getMethod, fieldType, maxFieldName, unName, unName));
                    //p.field.AppendLine(string.Format("private {0} {1} = {2}", fieldType, fieldName, defaultVal));
                }
            }

            return p;
        }

        public class LayaRefSB
        {
            public StringBuilder fieldCall = new StringBuilder();
            public StringBuilder field = new StringBuilder();
            public StringBuilder fieldUn = new StringBuilder();
            public StringBuilder property = new StringBuilder();
            public StringBuilder initMethod = new StringBuilder();
            public StringBuilder saveMethod = new StringBuilder();
            public StringBuilder virtualMethod = new StringBuilder();

            public string GetClassContent()
            {
                return field.ToString() + fieldCall + fieldUn + property + virtualMethod;
            }
        }

        public class DefineLayaScript
        {
            public static string boolProperty = "private {0} {1} \n" +
                                                "{{\n" +
                                                "get {{ return {2} > 0; }}\n" +
                                                "set{{\n" +
                                                "if({2} == value)\n" +
                                                "return;\n" +
                                                "{2} = value\n" +
                                                "PlayerPrefs.SetInt({3}, {2});\n" +
                                                "}}\n" +
                                                "}}\n";


            public static string templateClass = "using System.Collections;\n" +
                                                 "using System.Collections.Generic;\n" +
                                                 "using System;\n" +
                                                 "using UnityEngine;\n" +
                                                 "using System.IO;\n" +
                                                 "using UFrame;\n" +
                                                 "public class ${className} : Singleton<${className}>\n" +
                                                 "{\n" +
                                                 "public static Level I;" +
                                                 "Level()" +
                                                 "{" +
                                                 "if(I == null)" +
                                                 "I = this;" +
                                                 "}" +
                                                 "${classContent}\n" +
                                                 "${classLoad}\n" +
                                                 "${classSave}\n" +
                                                 "}\n";

            public static string loadMethod = "public void Load()\n" +
                                              "{\n" +
                                              "${classLoad}\n" +
                                              "}\n";

            public static string saveMethod = "public void Save()\n" +
                                              "{\n" +
                                              "${classSave}\n" +
                                              "}\n";
        }


    }
}